//
// Created by u on 23-6-29.
//

#ifndef MOSQUITTO_TEST_MQTTCOMMON_HPP
#define MOSQUITTO_TEST_MQTTCOMMON_HPP

#include <string>
#include <iostream>
#include <chrono>
#include <functional>
#include <vector>
#include <ctime>
#include <cassert>
#include <cstdarg>
#include <sstream>
#include <XLogger.hpp>

using namespace std;
using namespace std::chrono;
using namespace std::chrono_literals;

struct Msg;
struct timedTaskStruct;
class MqttClient;

using MqttReceiveParseMsgCallback = std::function<void(const Msg&)>;
using MqttMsgParseInitCallback = std::function<void(const std::shared_ptr<MqttClient>&)>;


struct Msg {
	std::string topic;
	std::string payload;
	int qos;

	Msg(const std::string& top, const std::string& payload, int qos = 0)
		: topic(top), payload(payload), qos(qos) {
	}

	Msg(const std::string&& top, const std::string&& payload, int qos = 0)
		: topic(top), payload(payload), qos(qos) {
	}

	friend std::ostream &operator<<(std::ostream& os, const Msg& msg) {
		LOG_DEBUG("topic: {} qos: {} payload: {}", msg.topic, msg.qos, msg.payload);
		return os;
	}
};


uint64_t getLocalTimeStampUs() {
	return std::chrono::duration_cast<std::chrono::microseconds>(
		std::chrono::system_clock::now().time_since_epoch()).count();
}

uint64_t getLocalTimeStampMs() {
	return std::chrono::duration_cast<std::chrono::milliseconds>(
		std::chrono::system_clock::now().time_since_epoch()).count();
}

uint64_t getLocalTimeStampS() {
	return std::chrono::duration_cast<std::chrono::seconds>(
		std::chrono::system_clock::now().time_since_epoch()).count();
}

template<class Rep, class Period>
std::chrono::duration<long, std::micro> formatToSystemTimeStampMs(std::chrono::duration<Rep, Period> time) {
	return std::chrono::duration_cast<std::chrono::microseconds>(time);
}

/* 计算两个相同字符之间的长度（跳过前几个字符）*/
size_t countDistance(const std::string& str, char c, size_t skipCount = 0) {
	size_t count = 0;
	size_t pos = str.find(c);
	size_t skip = 0;

	while (pos != std::string::npos) {
		if (skip >= skipCount) {
			size_t nextPos = str.find(c, pos + 1);
			if (nextPos != std::string::npos) {
				count += nextPos - pos - 1;
				pos = nextPos;
			} else {
				break;
			}
		} else {
			++skip;
			pos = str.find(c, pos + 1);
		}
	}

	return count;
}

#define DeviceSn                          		"0120000F230728000001"

#define ProductKey                          	"dztqlv3fba3o"
#define DeviceKey								"aynsnfrxlezn"

/* SPTU-NXA */
// #define ProductKey_SUB                          "njxsppemnu88"
// #define DeviceKey_SUB							"yuhkib7ca2ub"
/* SPTU-M8 */
#define ProductKey_SUB                          "rx0vvs6vpfvt"
#define DeviceKey_SUB							"2y4i9agiph4v"

/* 定义物联网平台 dev--泰智慧 iot--iot平台 */
#define MQTT_PLATFORM                           "iot"
/* 组网命令下发 */
#define MQTT_TOPIC_DEVICE_TOPO_CHANGE			MQTT_PLATFORM "/" ProductKey "/" DeviceKey "/topo/change"
/* 添加拓扑结构 */
#define MQTT_TOPIC_DEVICE_TOPO_ADD				MQTT_PLATFORM "/" ProductKey "/" DeviceKey "/topo/add"
/* 添加拓扑结构 */
#define MQTT_TOPIC_DEVICE_TOPO_DEL				MQTT_PLATFORM "/" ProductKey "/" DeviceKey "/topo/delete"
/* 子设备数据上报 */
#define MQTT_TOPIC_DEVICE_REPORT       			MQTT_PLATFORM "/" ProductKey "/" DeviceKey "/sub/point/report"
/* 子设备控制 */
#define MQTT_TOPIC_DEVICE_CONTROL           	MQTT_PLATFORM "/" ProductKey "/" DeviceKey "/actions/execute"

class MqttConnectInfo {
public:
	std::string server;
	int port;
	std::string clientID;
	std::string user;
	std::string passwd;
	bool cleanSession;
	int keepAlive;

	MqttConnectInfo()
	: server(""), port(-1), clientID(""), user(""), passwd(""), cleanSession(true), keepAlive(60){

	}
	MqttConnectInfo(const std::string& serv, int port, const std::string &clientId,
		const std::string& user = "", const std::string& pwd="", bool cleanSession=true, int keepAlive=60)
		: server(serv), port(port), clientID(clientId), user(user), passwd(pwd), cleanSession(cleanSession), keepAlive(keepAlive){

	}
};

#endif //MOSQUITTO_TEST_MQTTCOMMON_HPP
